package xyz.lwm.lazycat.jdkhttp;

import xyz.lwm.lazycat.utility.PathUtil;
import xyz.lwm.lazycat.utility.StringUtil;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static xyz.lwm.lazycat.utility.StrPool.STR_LEFT_BRACE;
import static xyz.lwm.lazycat.utility.StrPool.STR_RIGHT_BRACE;
import static xyz.lwm.lazycat.utility.StrPool.STR_SLASH;

abstract class JdkParamUtil {

    // copy from hutool
    public static Map<String, List<String>> parseParams(String query, Charset charset) {
        if (StringUtil.isBlank(query)) {
            return Collections.emptyMap();
        }
        Map<String, List<String>> params = new HashMap<>();

        final int len = query.length();
        String name = null;
        int pos = 0; // 未处理字符开始位置
        int i; // 未处理字符结束位置
        char c; // 当前字符
        for (i = 0; i < len; i++) {
            c = query.charAt(i);
            switch (c) {
                case '='://键和值的分界符
                    if (null == name) {
                        // name可以是""
                        name = query.substring(pos, i);
                        // 开始位置从分节符后开始
                        pos = i + 1;
                    }
                    // 当=不作为分界符时，按照普通字符对待
                    break;
                case '&'://键值对之间的分界符
                    addParam(params, name, query.substring(pos, i), charset);
                    name = null;
                    if (i + 4 < len && "amp;".equals(query.substring(i + 1, i + 5))) {
                        // issue#850@Github，"&amp;"转义为"&"
                        i += 4;
                    }
                    // 开始位置从分节符后开始
                    pos = i + 1;
                    break;
            }
        }

        // 处理结尾
        addParam(params, name, query.substring(pos, i), charset);

        return params;
    }

    private static void addParam(Map<String, List<String>> params, String key, String value, Charset charset) {
        if (key != null) {
            value = value == null ? null : decode(value, charset);
            params.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
        } else if (value != null) {
            value = decode(value, charset);
            params.computeIfAbsent(value, k -> new ArrayList<>()).add(null);
        }
    }


    public static String decode(String str, Charset charset) {
        try {
            return URLDecoder.decode(str, charset.toString());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String encode(String str, Charset charset) {
        try {
            return URLEncoder.encode(str, charset.toString());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static Map<String, String> parsePathParams(String routePath, String requestPath) {
        if (StringUtil.isBlank(routePath) || StringUtil.isBlank(requestPath) ||
                !routePath.contains(STR_LEFT_BRACE) || routePath.equals(requestPath)) {
            return Collections.emptyMap();
        }

        Map<String, String> pathParams = new LinkedHashMap<>();

        routePath = PathUtil.normalizePath(routePath);
        requestPath = PathUtil.normalizePath(requestPath);
        String[] routeStrArr = routePath.split(STR_SLASH);
        String[] requestStrArr = requestPath.split(STR_SLASH);
        for (int i = 0; i < routeStrArr.length; i++) {
            String routeStr = routeStrArr[i];
            if (routeStr.startsWith(STR_LEFT_BRACE) && routeStr.endsWith(STR_RIGHT_BRACE)) {
                String name = routeStr.substring(1, routeStr.length() - 1);
                String value = requestStrArr[i];
                pathParams.put(name, value);
            }
        }
        return pathParams;
    }

}
